#include "network.hh"
#include "../logger/writer.hh"
#include "../util/string_util.hh"
#include <regex>

using namespace kratos::corelib;

namespace kratos {
namespace network {

Session::Session()
    : channel_(0), sessionID_(0), writer_(this), selector_(nullptr), userData_(0), closed_(false), userPtr_(nullptr) {
}

Session::Session(std::uint64_t channel, Selector<Session>* selector)
    : channel_(channel), sessionID_(0), writer_(this), selector_(selector), userData_(0), closed_(false), userPtr_(nullptr) {
}

Session::~Session() {
}

void Session::talk(const char* data, std::uint32_t size) {
    selector_->send(channel_, data, size, selector_->getIoType());
}

SessionReader& Session::getReader() {
    return reader_;
}

SessionWriter & Session::getWriter() {
    return writer_;
}

void Session::close() {
    if (closed_) {
        return;
    }
    closed_ = true;
    selector_->close(sessionID_);
}

std::uint32_t Session::getID() const {
    return sessionID_;
}

void Session::timerTask(std::time_t timeout, SessionTimerHandler timerHandler) {
    registerEventHandler(static_cast<std::uint32_t>(network::EventID::EventID_Timer), timerHandler);
    network::fireTimedEventMillion<network::EventTarget>(timeout, static_cast<std::uint32_t>(network::EventID::EventID_Timer),
        Object::getID());
}

PacketFilter& Session::getPacketFilter() {
    return packetFilter_;
}

Session::operator bool() {
    return (channel_ != 0);
}

void Session::setUserData(std::uint64_t userData) {
    userData_ = userData;
}

std::uint64_t Session::getUserData() {
    return userData_;
}

IoLoopType Session::getIoType() {
    return selector_->getIoType();
}

SelectorType Session::getSelectorType() {
    return selector_->getType();
}

void Session::setUserPtr(void * ptr) {
    userPtr_ = ptr;
}

void * Session::getUserPtr() {
    return userPtr_;
}

Selector<Session>* Session::getSelector() {
    return selector_;
}

std::uint64_t Session::getChannelID() const {
    return channel_;
}

void Session::setID(std::uint32_t sessionID) {
    sessionID_ = sessionID;
}

SelectorConfig::SelectorConfig()
    : port_(0) {
}

SelectorConfig::SelectorConfig(const std::string& config)
: port_(0), ok_(false) {
    reset(config);
}

SelectorConfig::~SelectorConfig() {
}

const std::string & SelectorConfig::ip() const {
    return ip_;
}

const std::uint16_t SelectorConfig::port() const {
    return port_;
}

SelectorConfig::operator bool() {
    return ok_;
}

void SelectorConfig::reset(const std::string & config) {
    std::vector<std::string> result;
    corelib::StringUtil::split(config, ":", result);
    if (result.size() < 2) {
        return;
    }
    ip_ = result[0];
    port_ = static_cast<std::uint16_t>(std::stoi(result[1]));
    ok_ = true;
}

SessionWriter::SessionWriter(Session * session)
: session_(session) {
}

void SessionWriter::talk(const char * data, std::uint32_t size) {
    if (size) {
        session_->talk(data, size);
    }
}

PacketFilter::PacketFilter()
    : last_(0) {
}

bool PacketFilter::filter(SessionReader & reader) {
    if (filterMethod_) {
        if (filterMethod_(reader, last_)) {
            last_ = 0;
            return true;
        }
        return false;
    }
    return true;
}

void PacketFilter::onFilter(PacketFilterMethod method) {
    filterMethod_ = method;
}

}
}
